package linc.cool.robot.simple;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.parser.Feature;
import com.mzlion.easyokhttp.HttpClient;
import linc.cool.robot.constants.LeetCodeConstants;
import linc.cool.robot.leetcode.LeetCodeProblem;
import lombok.extern.slf4j.Slf4j;
import love.forte.simbot.annotation.Filter;
import love.forte.simbot.annotation.FilterValue;
import love.forte.simbot.annotation.OnPrivate;
import love.forte.simbot.api.message.containers.AccountInfo;
import love.forte.simbot.api.message.events.PrivateMsg;
import love.forte.simbot.api.sender.MsgSender;
import love.forte.simbot.filter.MatchType;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;

import javax.annotation.PostConstruct;
import javax.annotation.Resource;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @author yqlin
 * @date 2022/4/8 21:10
 * @description
 */
@Slf4j
@Component("simpleBotLeetCodeEvent")
public class SimpleBotLeetCodeEvent {
    Map<String, LeetCodeProblem> problemsMap;

    @Value("${qq.owner}")
    private String ownerCode;
    @Value("${qq.group}")
    private String groupCode;

    /***
     * 指令实现: check_leetcode_problem [题目名] #代码#
     * check_leetcode_problem reverse-linked-list #
     * public class Solution {
     *   public ListNode detectCycle(ListNode head) {
     *         if (head == null) return null;
     *         ListNode fast = head, slow = head;
     *         while (fast != null && fast.next != null) {
     *             slow = slow.next;
     *             fast = fast.next.next;
     *             if (fast == slow) {
     *                 break;
     *             }
     *         }
     *         // 上面的代码类似 hasCycle 函数
     *         if (fast == null || fast.next == null) {
     *             // fast 遇到空指针说明没有环
     *             return null;
     *         }
     *         // 将快指针置回头部,慢指针每次走一步,快指针也每次走一步,直到相遇
     *         fast = head;
     *         // 快慢指针同步前进，相交点就是环起点
     *         while (fast != slow) {
     *             fast = fast.next;
     *             slow = slow.next;
     *         }
     *         return fast;
     *     }
     * }
     * #
     */
    @PostConstruct
    public void initProblems() {
        Set<LeetCodeProblem> members = redisTemplate.opsForSet().members(LeetCodeConstants.PROBLEMS_SET_KEY);
        if (CollectionUtils.isEmpty(members)) {
            return;
        }
        problemsMap = members.stream().collect(Collectors.toMap(LeetCodeProblem::getTitleSlug, k -> k, (v1, v2) -> v1));
        log.info("leetcode题目加载成功,加载题目数量: {}......", members.size());
    }


    @Resource
    private RedisTemplate<String, LeetCodeProblem> redisTemplate;

    @OnPrivate
    @Filter(value = "check_leetcode_problem\s(?<problem>.{1,100})\s#(?<code>[\\s\\S]+)#$", matchType = MatchType.REGEX_MATCHES, trim = true)
    public void doPrivateMsg(PrivateMsg event, MsgSender sender, @FilterValue("problem") String problem, @FilterValue("code") String code) {
        AccountInfo accountInfo = event.getAccountInfo();
        if (ownerCode.equals(accountInfo.getAccountCode())) {
            System.out.println(code);
            System.out.println(problem);
            /**
             * TOOD
             */
            LeetCodeProblem problemInfo = problemsMap.get(problem);
            if (Objects.isNull(problemInfo)) {
                sender.SENDER.sendPrivateMsgAsync(ownerCode, "当前题目不存在", code);
            }
            Map<String, Object> submitRequestMap = new HashMap<>(8);
            submitRequestMap.put("question_id", problemInfo.getFrontendQuestionId());
            submitRequestMap.put("lang", "java");
            submitRequestMap.put("false", false);
            submitRequestMap.put("test_judger", "amet ea ut laboris ad");
            submitRequestMap.put("questionSlug", "problem");
            submitRequestMap.put("typed_code", code);
            // 发送http请求
            String submitJson = HttpClient.textBody(LeetCodeConstants.BASIC_URI + "/problems/" + problem + "/submit/")
                    .json(JSON.toJSONString(submitRequestMap))
                    .header("cookie", LeetCodeConstants.COOKIE)
                    .header("origin", LeetCodeConstants.BASIC_URI)
                    .asString();
            JSON.DEFAULT_PARSER_FEATURE &= ~Feature.UseBigDecimal.getMask();
            Map<?, ?> submitMap = JSON.parseObject(submitJson, Map.class);
            String submissionId = String.valueOf(submitMap.get("submission_id"));
            String statusCode;
            Map<?, ?> checkMap;
            do {
                String checkJson = HttpClient.get(LeetCodeConstants.BASIC_URI + "/submissions/detail/" + submissionId + "/check/")
                        .header("cookie", LeetCodeConstants.COOKIE)
                        .header("origin", LeetCodeConstants.BASIC_URI)
                        .asString();
                checkMap = JSON.parseObject(checkJson, Map.class);
                statusCode = String.valueOf(checkMap.get("status_code"));
                System.out.println(statusCode);
            } while (!statusCode.equals("10"));
            String template = """
                    ===============================提交结果==========================
                                        
                    题目: %s.%s                   
                    提交时间: %s
                    执行结果: %s          
                    执行用时: %s ms,在所有 Java 提交中击败了%s %%的用户
                    内存消耗: %s , 在所有 Java 提交中击败了%s %%的用户
                    提交的代码:                           
                    %s            
                    ===============================================================
                    """;
            // 提交时间
            long taskFinishTime = Long.parseLong(String.valueOf(checkMap.get("task_finish_time")));
            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
            String taskFinishTimeStr = sdf.format(new Date(taskFinishTime));
            // 执行结果
            String runSuccess = String.valueOf(checkMap.get("run_success"));
            // 执行用时
            Integer displayRuntime = Integer.valueOf(String.valueOf(checkMap.get("display_runtime")));
            //  执行用时击败了多少用户的百分比
            String runtimePercentile = String.valueOf(checkMap.get("runtime_percentile"));
            // 内存消耗
            String statusMemory = String.valueOf(checkMap.get("status_memory"));
            // 内存消耗击败了多少用户的百分比
            String memoryPercentile = String.valueOf(checkMap.get("memory_percentile"));
            sender.SENDER.sendPrivateMsgAsync(ownerCode, String.format(template, problemInfo.getFrontendQuestionId(), problem, taskFinishTimeStr, runSuccess, displayRuntime, runtimePercentile, statusMemory, memoryPercentile, code));

        }
    }
}
